package net.wangds.utils;

import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.util.Calendar;
import java.util.Date;
import java.util.Objects;

/**
 * Cp56Time2a协议.
 * <p></p>
 *
 * @author wangds 2020/10/12 21:52.
 */
public class Cp56Time2aUtils {

    public static Date toDate(byte[] data){
        Objects.requireNonNull(data);
        if(data.length<7){
            throw new IndexOutOfBoundsException("CP56time2a格式时间至少需要7字节，数据长度不够："+HexUtils.bytes2HexString(data));
        }
        return toDate(ByteBuffer.wrap(data, 0, 7));
    }

    public static Date toDate(long cp56Time2aLongVal){
        ByteBuffer buf = ByteBuffer.allocate(8);
        buf.putLong(cp56Time2aLongVal);
        buf.position(1); //skip 最高一位
        buf.compact();
        return toDate(buf);
    }

    private static Date toDate(ByteBuffer buf) {

        if(buf.remaining()<7){
            buf.mark();
            byte[] data = new byte[buf.remaining()];
            buf.get(data);
            buf.reset();
            throw new IndexOutOfBoundsException("CP56time2a格式时间至少需要7字节，数据长度不够："+HexUtils.bytes2HexString(data));
        }
        ByteOrder oldOrder = buf.order();
        buf.order(ByteOrder.LITTLE_ENDIAN);
        int ms = Short.toUnsignedInt(buf.getShort()); // pos 0, 2

        byte tmp = buf.get(); // pos 2
        int minutes = tmp&0x3F; //分钟
        //int res1 = ((tmp>>6)&1); //RES1
        int iv = ((tmp>>7)&1); //IV 0=有效；1=无效

        tmp = buf.get(); //pos 3
        int hours = tmp&0x1F;
        //int res2 = ((tmp>>5)&0x3);
        //int su = ((tmp>>7)&0x1); //SU 0=标准时间;1=夏季时间

        tmp = buf.get(); //pos 4
        int dayOfMonth = tmp&0x1F;
        //int dayOfWeek = ((tmp>>5)&0x7);

        tmp = buf.get(); //pos 5
        int month = tmp*0xF;
        //int res3 = ((tmp>>4)&0xF);

        tmp = buf.get(); //pos 6
        int years = tmp&0x7F;
        //int res4 = (tmp>>7)&0x1;
        buf.order(oldOrder);

        Calendar cal = Calendar.getInstance();

        int sec = ms/1000;
        ms = ms%1000;

        cal.set(Calendar.MILLISECOND, ms);
        cal.set(Calendar.SECOND, sec);
        cal.set(Calendar.MINUTE, minutes);
        cal.set(Calendar.HOUR_OF_DAY, hours);
        cal.set(Calendar.DAY_OF_MONTH, dayOfMonth);
        cal.set(Calendar.MONTH, month-1);
        cal.set(Calendar.YEAR, 2000+years);

        return cal.getTime();
    }


    /**
     * 日期转换为CP56Time2a格式
     * @param date 日期.
     * @return 读取状态.
     */
    public static ByteBuffer toBuffer(Date date){
        ByteBuffer buf = ByteBuffer.allocate(7);

        buf.order(ByteOrder.LITTLE_ENDIAN);//调整字节序，毫秒数据写入short类型，需要指定

        Calendar cal = Calendar.getInstance();
        cal.setTime(date);

        int ms = cal.get(Calendar.MILLISECOND);
        int sec = cal.get(Calendar.SECOND);
        int min = cal.get(Calendar.MINUTE);
        int h = cal.get(Calendar.HOUR_OF_DAY);
        int d = cal.get(Calendar.DAY_OF_MONTH);
        int m = cal.get(Calendar.MONTH)+1;
        int y = cal.get(Calendar.YEAR)-2000;
        int w = cal.get(Calendar.DAY_OF_WEEK);

        int week;
        switch(w){
            case Calendar.MONDAY:
                week = 1;
                break;
            case Calendar.TUESDAY:
                week = 2;
                break;
            case Calendar.WEDNESDAY:
                week = 3;
                break;
            case Calendar.THURSDAY:
                week = 4;
                break;
            case Calendar.FRIDAY:
                week = 5;
                break;
            case Calendar.SATURDAY:
                week = 6;
                break;
            case Calendar.SUNDAY:
            default:
                week = 7;
        }

        int secAndMs = sec*1000+ms;
        buf.putShort((short)secAndMs); //pos 0,1
        buf.put((byte)min);//pos 2
        buf.put((byte)h);//pos 3
        byte b4 = (byte)(((week<<5)&0xE0)|(d&0x1F));
        buf.put(b4); //pos 4
        buf.put((byte)m);//pos 5
        buf.put((byte)y);

        buf.flip();
        return buf;
    }


    /**
     * 日期转换为CP56Time2a格式
     * @param date 日期.
     * @return CP56Time2a格式字节数组.
     */
    public static byte[] toBytes(Date date) {
        return toBuffer(date).array();
    }



}
